package com.beimihu.GetAFData.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * Created by shenjunjie
 * on 2022/7/19.
 */
public class HttpRequestor {
    private static final Logger log = LoggerFactory.getLogger(HttpRequestor.class);
    private String charset = "utf-8";
    private Integer connectTimeout = null;
    private Integer socketTimeout = null;
    private String proxyHost = "127.0.0.1";
    private Integer proxyPort = 7890;

    /**
     * Do GET request
     *
     * @param url
     * @return String
     * @throws Exception
     * @throws IOException
     */

    public String doGet(String url) throws Exception {
        URL localURL = new URL(url);
        System.out.println("-> GET url = " + url);
        URLConnection connection = this.openConnection(localURL);
        HttpURLConnection httpURLConnection = (HttpURLConnection) connection;

        if (httpURLConnection == null) {
            throw new Exception("HTTP Request is not success, HttpURLConnection is null");
        }

        httpURLConnection.setRequestProperty("Accept-Charset", charset);
        httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader reader = null;
        StringBuffer resultBuffer = new StringBuffer();
        String tempLine = null;
        if (httpURLConnection.getResponseCode() >= 300) {
            InputStream errStream = httpURLConnection.getErrorStream();
            inputStreamReader = new InputStreamReader(errStream);
            reader = new BufferedReader(inputStreamReader);
            while ((tempLine = reader.readLine()) != null) {
                resultBuffer.append(tempLine);
            }
            return resultBuffer.toString();
        }

        try {
            inputStream = httpURLConnection.getInputStream();
            inputStreamReader = new InputStreamReader(inputStream);
            reader = new BufferedReader(inputStreamReader);

            while ((tempLine = reader.readLine()) != null) {
                resultBuffer.append(tempLine);
            }

        } finally {

            if (reader != null) {
                reader.close();
            }

            if (inputStreamReader != null) {
                inputStreamReader.close();
            }

            if (inputStream != null) {
                inputStream.close();
            }

        }
        return resultBuffer.toString();
    }


    public String sendGetRequest(String url) {
        try {
            URL getUrl = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();

            // 设置请求方法为 GET
            connection.setRequestMethod("GET");

            // 发起请求
            int responseCode = connection.getResponseCode();

            // 读取响应数据
            if (responseCode == HttpURLConnection.HTTP_OK) {
                try (InputStream inputStream = connection.getInputStream();
                     InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                     BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = bufferedReader.readLine()) != null) {
                        response.append(line);
                    }
                    return response.toString();
                }
            } else {
                System.out.println("HTTP Request is not success, Response code is " + responseCode);
            }

            connection.disconnect();
        } catch (Exception e) {
            System.out.println("Error occurred while sending GET request to URL: " + url);
            e.printStackTrace();
        }

        return null;
    }


    public String doGet(String url, Map<String, String> header) throws Exception {
        URL localURL = new URL(url);
        System.out.println("-> GET url = " + url);
        URLConnection connection = this.openConnection(localURL);
        HttpURLConnection httpURLConnection = (HttpURLConnection) connection;

        if (httpURLConnection == null) {
            throw new Exception("HTTP Request is not success, HttpURLConnection is null");
        }

        httpURLConnection.setRequestProperty("Accept-Charset", charset);
        httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        for (String key : header.keySet()) {
            httpURLConnection.setRequestProperty(key, header.get(key));
        }
        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader reader = null;
        StringBuffer resultBuffer = new StringBuffer();
        String tempLine = null;
        if (httpURLConnection.getResponseCode() >= 300) {
            throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
        }

        try {
            inputStream = httpURLConnection.getInputStream();
            inputStreamReader = new InputStreamReader(inputStream);
            reader = new BufferedReader(inputStreamReader);

            while ((tempLine = reader.readLine()) != null) {
                resultBuffer.append(tempLine);
            }

        } finally {

            if (reader != null) {
                reader.close();
            }

            if (inputStreamReader != null) {
                inputStreamReader.close();
            }

            if (inputStream != null) {
                inputStream.close();
            }

        }
        return resultBuffer.toString();
    }

    public int download(String url, Map<String, String> header, File file) throws Exception {
        URL localURL = new URL(url);
        System.out.println("-> GET url = " + url);
        URLConnection connection = this.openConnection(localURL);
        HttpURLConnection httpURLConnection = (HttpURLConnection) connection;

        if (httpURLConnection == null) {
            throw new Exception("HTTP Request is not success, HttpURLConnection is null");
        }

        httpURLConnection.setRequestProperty("Accept-Charset", charset);
        httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        for (String key : header.keySet()) {
            httpURLConnection.setRequestProperty(key, header.get(key));
        }
        InputStream inputStream = null;
        FileOutputStream fout = new FileOutputStream(file);

        //响应失败
        if (httpURLConnection.getResponseCode() >= 300) {
            throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode() + ",result:" + httpURLConnection.getResponseMessage());
        }

        inputStream = httpURLConnection.getInputStream();
        int i = 0;
        byte[] buff = new byte[1024];
        while ((i = inputStream.read(buff)) != -1) {
            fout.write(buff, 0, i);
        }
        if (inputStream != null) {
            inputStream.close();
        }
        if (fout != null) {
            fout.close();
        }
        return 1;
    }

    public InputStream getFileInputStream(String url, Map<String, String> header) throws Exception {
        URL localURL = new URL(url);
        System.out.println("-> GET url = " + url);
        URLConnection connection = this.openConnection(localURL);
        HttpURLConnection httpURLConnection = (HttpURLConnection) connection;

        if (httpURLConnection == null) {
            throw new Exception("HTTP Request is not success, HttpURLConnection is null");
        }

        httpURLConnection.setRequestProperty("Accept-Charset", charset);
        httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        for (String key : header.keySet()) {
            httpURLConnection.setRequestProperty(key, header.get(key));
        }
        InputStream inputStream = null;
        //响应失败
        if (httpURLConnection.getResponseCode() >= 300) {
            throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode() + ",result:" + httpURLConnection.getResponseMessage());
        }

        try {
            inputStream = httpURLConnection.getInputStream();
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return inputStream;
    }

    /**
     * Do POST request
     *
     * @param url
     * @param data
     * @return String
     * @throws Exception
     */
    public String doPost(String url, String data) throws Exception {

        /* Translate parameter map to parameter date string */
        StringBuffer parameterBuffer = new StringBuffer();
        parameterBuffer.append(data);
        System.out.println("-> POST url = " + url + " -->parameter : " + parameterBuffer);

        URL localURL = new URL(url);

        URLConnection connection = this.openConnection(localURL);
        HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
        if (httpURLConnection == null) {

            throw new Exception("HTTP Request is not success, HttpURLConnection is null");
        }
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36");
        httpURLConnection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
        httpURLConnection.setRequestProperty("Accept-Charset", charset);
        httpURLConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        httpURLConnection.setRequestProperty("Content-Length", parameterBuffer.toString().length()+"");

        OutputStream outputStream = null;
        OutputStreamWriter outputStreamWriter = null;
        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader reader = null;
        StringBuilder resultBuffer = new StringBuilder();
        String tempLine = null;

        try {
            outputStream = httpURLConnection.getOutputStream();
            outputStreamWriter = new OutputStreamWriter(outputStream);

            outputStreamWriter.write(parameterBuffer.toString());
            outputStreamWriter.flush();
            //响应失败
            if (httpURLConnection.getResponseCode() >= 300) {
                throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
            }
            inputStream = httpURLConnection.getInputStream();
            inputStreamReader = new InputStreamReader(inputStream);
            reader = new BufferedReader(inputStreamReader);

            while ((tempLine = reader.readLine()) != null) {
                resultBuffer.append(tempLine);
            }

        } catch (Exception e) {
            log.error("doPost","HTTP Output Error"+e.getMessage());
            throw new Exception("HTTP Output Error  " + e.getMessage());
        } finally {

            if (outputStreamWriter != null) {
                outputStreamWriter.close();
            }

            if (outputStream != null) {
                outputStream.close();
            }

            if (reader != null) {
                reader.close();
            }

            if (inputStreamReader != null) {
                inputStreamReader.close();
            }

            if (inputStream != null) {
                inputStream.close();
            }

        }
        return resultBuffer.toString();
    }

    public String doPostByform(String url, HashMap<String,String> parameters) throws Exception

    {
        try {
            StringBuffer parameterBuffer = new StringBuffer();
            parameterBuffer.append(parameters);
            System.out.println("-> POST url = " + url + " -->parameter : " + parameterBuffer);
            // 创建URL对象
            URL apiUrl = new URL(url);

            // 创建HttpURLConnection对象
            HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);

            // 使用TreeMap按照键的字母升序排列参数
            TreeMap<String, String> sortedParameters = new TreeMap<>(parameters);

            // 构建x-www-form-urlencoded格式的请求参数
            StringBuilder requestBody = new StringBuilder();
            for (Map.Entry<String, String> entry : sortedParameters.entrySet()) {
                requestBody.append(entry.getKey())
                        .append("=")
                        .append(entry.getValue())
                        .append("&");
            }
            requestBody.deleteCharAt(requestBody.length() - 1);  // 删除末尾的"&"

            System.out.println("param："+requestBody);
            // 设置请求头
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            // 发送请求
            try (OutputStream outputStream = connection.getOutputStream()) {
                byte[] requestBodyBytes = requestBody.toString().getBytes(StandardCharsets.UTF_8);
                outputStream.write(requestBodyBytes);
                outputStream.flush();
            }

            // 获取响应
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 处理成功响应
                // 读取响应内容
                StringBuilder response = new StringBuilder();
                try (BufferedReader reader = new BufferedReader(
                        new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        response.append(line);
                    }
                }
                return response.toString();
            } else {
                StringBuilder errorMsg = new StringBuilder();
                try (BufferedReader errorReader = new BufferedReader(
                        new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8))) {
                    String errorLine;
                    while ((errorLine = errorReader.readLine()) != null) {
                        errorMsg.append(errorLine);
                    }
                }
                return String.valueOf(responseCode) + ": " + errorMsg.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }



    public String sendPostRequest(String url, String data) {
        try {
            URL postUrl = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) postUrl.openConnection();

            // 设置请求方法为 POST
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);

            // 设置请求体的内容类型
            connection.setRequestProperty("Content-Type", "application/json");

            // 将数据编码为字节数组
            byte[] postData = data.getBytes(StandardCharsets.UTF_8);

            // 将数据写入请求体
            try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
                outputStream.write(postData);
                outputStream.flush();
            }

            // 发起请求
            int responseCode = connection.getResponseCode();

            // 读取响应数据
            if (responseCode == HttpURLConnection.HTTP_OK) {
                try (InputStream inputStream = connection.getInputStream()) {
                    StringBuilder response = new StringBuilder();
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        response.append(new String(buffer, 0, bytesRead, StandardCharsets.UTF_8));
                    }
                    return response.toString();
                }
            } else {
                System.out.println("HTTP Request is not success, Response code is " + responseCode);
            }

            connection.disconnect();
        } catch (Exception e) {
            System.out.println("Error occurred while sending POST request to URL: " + url);
            e.printStackTrace();
        }

        return null;
    }

    public String doPost(String url, String data, Map<String, String> header) throws Exception {
        /* Translate parameter map to parameter date string */
        StringBuffer parameterBuffer = new StringBuffer();
        parameterBuffer.append(data);
        System.out.println("-> POST url = " + url + " -->parameter : " + parameterBuffer);

        URL localURL = new URL(url);

        URLConnection connection = this.openConnection(localURL);
        HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
        if (httpURLConnection == null) {
            throw new Exception("HTTP Request is not success, HttpURLConnection is null");
        }
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36");
        httpURLConnection.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
        httpURLConnection.setRequestProperty("Accept-Charset", charset);
        httpURLConnection.setRequestProperty("Content-Type", "application/json");
//        httpURLConnection.setRequestProperty("Content-Length", parameterBuffer.toString().length()+"");
        for (String key : header.keySet()) {
            httpURLConnection.setRequestProperty(key, header.get(key));
        }
        OutputStream outputStream = null;
        OutputStreamWriter outputStreamWriter = null;
        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        BufferedReader reader = null;
        StringBuilder resultBuffer = new StringBuilder();
        String tempLine = null;

        try {
            outputStream = httpURLConnection.getOutputStream();
            outputStreamWriter = new OutputStreamWriter(outputStream);

            outputStreamWriter.write(parameterBuffer.toString());
            outputStreamWriter.flush();
            //响应失败
            if (httpURLConnection.getResponseCode() >= 300) {
                throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
            }
            inputStream = httpURLConnection.getInputStream();
            inputStreamReader = new InputStreamReader(inputStream);
            reader = new BufferedReader(inputStreamReader);

            while ((tempLine = reader.readLine()) != null) {
                resultBuffer.append(tempLine);
            }

        } catch (Exception e) {
            throw new Exception("HTTP Output Error  " + e.getMessage());
        } finally {

            if (outputStreamWriter != null) {
                outputStreamWriter.close();
            }

            if (outputStream != null) {
                outputStream.close();
            }

            if (reader != null) {
                reader.close();
            }

            if (inputStreamReader != null) {
                inputStreamReader.close();
            }

            if (inputStream != null) {
                inputStream.close();
            }

        }
        return resultBuffer.toString();
    }

    private URLConnection openConnection(URL localURL) throws IOException {
        URLConnection connection;
        if (proxyHost != null && proxyPort != null) {
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
            connection = localURL.openConnection(proxy);
        } else {
            connection = localURL.openConnection();
        }
        return connection;
    }

    /**
     * Render request according setting
     *
     * @param connection
     */
    private void renderRequest(URLConnection connection) {

        if (connectTimeout != null) {
            connection.setConnectTimeout(connectTimeout);
        }

        if (socketTimeout != null) {
            connection.setReadTimeout(socketTimeout);
        }

    }

    /*
     * Getter & Setter
     */
    public Integer getConnectTimeout() {
        return connectTimeout;
    }

    public void setConnectTimeout(Integer connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    public Integer getSocketTimeout() {
        return socketTimeout;
    }

    public void setSocketTimeout(Integer socketTimeout) {
        this.socketTimeout = socketTimeout;
    }

    public String getProxyHost() {
        return proxyHost;
    }

    public void setProxyHost(String proxyHost) {
        this.proxyHost = proxyHost;
    }

    public Integer getProxyPort() {
        return proxyPort;
    }

    public void setProxyPort(Integer proxyPort) {
        this.proxyPort = proxyPort;
    }

    public String getCharset() {
        return charset;
    }

    public void setCharset(String charset) {
        this.charset = charset;
    }

}